import { Alert, Expander, ExpanderItem } from '@aws-amplify/ui-react';
import { AppDirectoryAlert } from '@/components/AppDirectoryAlert';
import { ComponentStyleDisplay } from '@/components/ComponentStyleDisplay';
import ReactPropsTable from '@/components/propsTable/ReactPropsTable';
import { Example, ExampleCode } from '@/components/Example';
import { Fragment } from '@/components/Fragment';
import { InstallScripts } from '@/components/InstallScripts';
import { STORAGE_MANAGER, FILE_PICKER, DROPZONE_PROPS, DISPLAY_TEXT } from './props';
import {
DefaultStorageManagerExample,
StorageManagerComponentOverridesExample,
StorageManagerDisplayTextExample,
StorageManagerEventExample,
StorageManagerFileTypesExample,
StorageManagerHashExample,
StorageManageri18nExample,
StorageManagerMetadataExample,
StorageManagerResumableExample,
StorageManagerThemeExample,
StorageManagerHandleExample,
} from './examples'
## Basic Usage
Did you follow the [quick start instructions](/connected-components/storage#quick-start) to set up the storage and auth services?
{({ platform }) => import('@/components/AppDirectoryAlert')}
To use the StorageManager component import it into your React application with the included styles.
```jsx
import { StorageManager } from '@aws-amplify/ui-react-storage';
import '@aws-amplify/ui-react/styles.css';
```
At a minimum you must include the `accessLevel` and `maxFileCount` props. `accessLevel` refers to the [Amplify Storage access level](https://docs.amplify.aws/lib/storage/configureaccess/q/platform/js/), which is `'public' | 'private' | 'protected'`.
```jsx file=./examples/DefaultStorageManagerExample.tsx
```
The uploading capabilities in these examples are stubbed out so they don't actually upload files anywhere!
### Props
## Setting Limits
You can limit what users upload with these 3 props:
* `maxFileSize`: sets a maximum file size the uploader will accept in bytes. The default is unlimited.
* `maxFileCount`: accepts how many files at one time you can select to upload.
* `acceptedFileTypes`: an array of file type strings that follow the [HTML `accept` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept).
```jsx file=./examples/StorageManagerFileTypesExample.tsx
```
## Pausable / Resumable Uploads
A resumable upload will upload the file in chunks. This allows users to pause an upload and resume it at a later time. You will typically want to do this only when the expected files are larger than the chunk size, which is 5MB.
```jsx file=./examples/StorageManagerResumableExample.tsx
```
## Pre-upload Processing
You might want to process or modify the file(s) and/or file name(s) before they are uploaded. One common situation is you may want to ensure files uploaded are at unique keys by hashing the file contents and using that as the key rather than the filename.
You can pass a `processFile` function to the StorageManager which accepts an object with `file`: [File](https://developer.mozilla.org/en-US/docs/Web/API/File), and `key`: string, and should return an object with file, key, and any other Storage configurations. The `processFile` can either return synchronously or return a Promise. This example uses a Promise to read the contents of the file and create a hash for the key.
```jsx file=./examples/StorageManagerHashExample.tsx
```
Other uses-cases for processing the file before upload:
1. Performing file optimizations like removing unnecessary metadata.
1. Performing custom file validations like reading the contents of a file to ensure it is in the proper structure.
You can also add any other [Amplify Storage options](https://docs.amplify.aws/lib/storage/upload/q/platform/js/#encrypted-uploads) by adding them to the return object of `processFile`
## Event Handling
The StorageManager component has several event handlers: `onUploadStart`, `onUploadSuccess`, `onUploadError`, and `onFileRemove`
```jsx file=./examples/StorageManagerEventExample.tsx
```
Be careful setting state in the `onUploadSuccess` because that function is bound when the upload _starts_. Make sure to use the previous state argument rather than the current state in the component.
## Adding metadata
Metadata is added as an object with string key-value pairs. It is sent as custom HTTP headers with the name `x-amz-meta-[key]`. For example, if your metadata for a file was `{mode: 'night'}`, it would set the `x-amz-meta-mode` HTTP header to `night`.
You can add metadata by adding a `metadata` object in the return object of `processFile`.
```jsx file=./examples/StorageManagerMetadataExample.tsx
```
## Customization
### Text and labels
All text in the StorageManager component is customizable with the `displayText` prop.
```jsx file=./examples/StorageManagerDisplayTextExample.tsx
```
### Internationalization
You can use the `displayText` prop to also support different languages. Use an open source library like i18next, react-intl, or make your own:
```jsx file=./examples/StorageManageri18nExample.tsx
```
### Component overrides
Don't like how things look? Use your own components inside the StorageManager! You can pass your own components with the `components` prop. The available components to override are: `Container`, `FileList`, `FileListHeader`, `DropZone`, and `FilePicker`.
_You can even use a completely different UI kit like MUI, Chakra, or your own design system!_
```jsx file=./examples/StorageManagerComponentOverridesExample.tsx
```
### Imperative handles
The `files` state is managed within the `StorageManager` component itself. To allow for clearing the internal `files` state, `StorageManager` exposes a custom ref handle to the parent component with a `clearFiles` method.
```jsx file=./examples/StorageManagerHandleExample.tsx
```
### Theming
```jsx file=./examples/StorageManagerThemeExample.tsx
```
### Target Classes
If you like, you can target classes directly or use CSS variables to make changes to the look and feel of the File Uploader.